from django.db.models import Q
import json
from django.shortcuts import render, reverse, redirect
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.core.cache import caches
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q
from django.http import HttpResponse, Http404
from django.views.generic import ListView, DetailView, View

from blog.models import Article, Category, Tag, Nav, Carousel, Recommend, Comment
from blog_system.models import Link, Like, AD

# Create your views here.

# 缓存
try:
    cache = caches['memcache']
except ImportError as e:
    cache = caches['default']


# 获取基础信息
class BaseMixin(object):
    def get_context_data(self, *args, **kwargs):
        context = super(BaseMixin, self).get_context_data(**kwargs)
        try:
            # 网站标题站点名称
            context['site_name'] = settings.SITE_NAME
            context['title_name'] = settings.TITLE_NAME
            # 导航栏
            context['nav_list'] = Nav.objects.filter().order_by('rank')
            # 阅读排行,后端提取全部数据,前端根据需要展示
            context['click_rank'] = Article.objects.filter().order_by('-view_count')
            # 站长推荐
            context['recommend_list'] = Recommend.objects.filter().order_by('rank')
            # 文章数量统计
            context['article_count'] = Article.objects.filter().count()
            # 文章评论统计
            context['comment_count'] = Comment.objects.all().count()
            # 标签云
            context['tag_list'] = Tag.objects.filter()
            # 广告
            context['ads'] = AD.objects.filter()
            # 点赞统计
            likes = Like.objects.all()
            like_nums = 0
            for i in likes:
                like_nums += i.num
            context['like_nums'] = like_nums

        except BaseException as e:
            print(e)

        return context


class IndexView(BaseMixin, ListView):
    template_name = 'index.html'
    context_object_name = 'new_article'

    def get_context_data(self, **kwargs):
        # 获取轮播图
        kwargs['carousel_list'] = Carousel.objects.filter()
        # 网站公告
        kwargs['notice_list'] = Article.objects.filter()
        # 友情链接
        kwargs['links'] = Link.objects.all()
        # 专题列表
        kwargs['zhuanti_list'] = Article.objects.filter()
        return super(IndexView, self).get_context_data(**kwargs)

    def get_queryset(self):
        new_article = Article.objects.filter().order_by('-is_top', '-pub_time')
        return new_article


# 文章详情视图
class ArticleView(BaseMixin, DetailView):
    queryset = Article.objects.filter()
    template_name = 'article.html'
    context_object_name = 'article'

    def get(self, request, *args, **kwargs):
        # 统计文章的访问次数
        if 'HTTP_X_FORWARDED_FOR' in request.META:
            ip = request.META['HTTP_X_FORWARDED_FOR']
        else:
            ip = request.META['REMOTE_ADDR']
        self.cur_user_ip = ip

        pk = self.kwargs.get('pk')
        # 获取15*60s时间内访问过这篇文章的所有ip
        visited_ips = cache.get(pk, [])

        # 如果ip不存在就把文章的浏览次数+1
        if ip not in visited_ips:
            try:
                article = self.queryset.get(id=str(pk))
            except Article.DoesNotExist:
                raise Http404
            else:
                article.view_count += 1
                article.save()
                visited_ips.append(ip)

            # 更新缓存
            cache.set(pk, visited_ips, 15 * 60)

        return super(ArticleView, self).get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        pk = self.kwargs.get('pk')
        # 上一篇文章
        kwargs['pre_article'] = Article.objects.filter(id__lt=pk, ).order_by(
            '-id').first()
        # 下一篇文章
        kwargs['next_article'] = Article.objects.filter(id__gt=pk, ).order_by(
            'id').first()
        # 相关文章
        kwargs['relate_article'] = \
            Article.objects.filter(~Q(id=pk),
                                   tag__name__in=list(Article.objects.filter(id=pk)[0].tag.all()))

        # 评论
        kwargs['comment_list'] = self.queryset.get(pk=str(pk)).comment_set.all()
        # 点赞
        if not Like.objects.filter(article_id=pk).exists():
            num = 0
            article = Article.objects.get(id=pk)
            Like.objects.create(num=num, article=article)
        else:
            num = Like.objects.get(article_id=pk).num
        kwargs['like_num'] = num
        return super(ArticleView, self).get_context_data(**kwargs)


# 所有文章列表视图
class AllView(BaseMixin, ListView):
    template_name = 'blog_list.html'
    context_object_name = 'article_list'

    def get_queryset(self):
        article_list = Article.objects.filter().order_by('-is_top', '-pub_time')
        # 每页显示数量
        page_article = Paginator(article_list, 10)
        try:
            article_list = page_article.page(self.request.GET.get('page'))
        # 判断页码是否是数值，如果不是，则返回第一页
        except PageNotAnInteger:
            article_list = page_article.page(1)
        except EmptyPage:
            article_list = page_article.page(page_article.num_pages)
        return article_list


# 查找文章列表视图
class SearchView(BaseMixin, ListView):
    template_name = 'blog_list.html'
    context_object_name = 'article_list'

    def get_queryset(self):
        # 根据关键词在标题/摘要/标签里查找是否有对应的内容
        keyboard = self.request.GET.get('keyboard', '')
        article_list = Article.objects.only(
            'title', 'summary', 'tag'
        ).filter(
            Q(title__icontains=keyboard) |
            Q(summary__icontains=keyboard) |
            Q(tag__name__icontains=keyboard),
        )
        page_article = Paginator(article_list, 10)
        try:
            article_list = page_article.page(self.request.GET.get('page'))
        # 判断页码是否是数值，如果不是，则返回第一页
        except PageNotAnInteger:
            article_list = page_article.page(1)
        except EmptyPage:
            article_list = page_article.page(page_article.num_pages)
        return article_list


# 文章分类列表视图
class CategoryView(BaseMixin, ListView):
    template_name = 'blog_list.html'
    context_object_name = 'article_list'

    def get_queryset(self):
        category = self.kwargs.get('category', '')
        try:
            article_list = Category.objects.get(name=category).article_set.filter()
            page_article = Paginator(article_list, 10)
            try:
                article_list = page_article.page(self.request.GET.get('page'))
            # 判断页码是否是数值，如果不是，则返回第一页
            except PageNotAnInteger:
                article_list = page_article.page(1)
            except EmptyPage:
                article_list = page_article.page(page_article.num_pages)
        except Category.DoesNotExist:
            raise Http404
        return article_list


class TagView(BaseMixin, ListView):
    template_name = 'blog_list.html'
    context_object_name = 'article_list'

    def get_queryset(self):
        tag = self.kwargs.get('tag', '')
        article_list = Article.objects.only('tag').filter(tag__name__icontains=tag)
        page_article = Paginator(article_list, 10)
        try:
            article_list = page_article.page(self.request.GET.get('page'))
        # 判断页码是否是数值，如果不是，则返回第一页
        except PageNotAnInteger:
            article_list = page_article.page(1)
        except EmptyPage:
            article_list = page_article.page(page_article.num_pages)
        return article_list


class CommentPostView(View):
    def post(self, request, * args, ** kwargs):
        username = self.request.POST.get('username', '')
        text = self.request.POST.get('comment', '')
        pk = self.kwargs.get('article_id', '')
        article = Article.objects.get(pk=str(pk))

        comment = Comment.objects.create(
            user_name=username,
            comment=text,
            article=article
        )
        return redirect(reverse('blog:article', kwargs={'pk': pk}))


# 实现点赞功能
@login_required
def like(request):
    pass

